#ifndef VISITOR_HPP
#define VISITOR_HPP

class Node;
class BitOrNode;
class BitXorNode;
class BitAndNode;
class LogicOrNode;
class LogicAndNode;
class LogicNotNode;
class LeftShiftNode;
class RightShiftNode;
class AddNode;
class SubNode;
class MulNode;
class DivNode;
class ListNode;
class ConstInt;
class ConstBool;
class ConstString;
class ConstChar;
class VarNode;
class VarDefNode;
class TypeDefNode;
class AssignNode;
class LambdaDef;
class CallNode;
class PrintNode;
class PrintlnNode;
class IfNode;
class CmpNode;

class Visitor {
public:
    void visit_node(Node* n);

    virtual void visit(BitOrNode* n) = 0;
    virtual void visit(BitXorNode* n) = 0;
    virtual void visit(BitAndNode* n) = 0;
    virtual void visit(LogicOrNode* n) = 0;
    virtual void visit(LogicNotNode* n) = 0;
    virtual void visit(LogicAndNode* n) = 0;
    virtual void visit(LeftShiftNode* n) = 0;
    virtual void visit(RightShiftNode* n) = 0;

    virtual void visit(AddNode* n) = 0;
    virtual void visit(SubNode* n) = 0;
    virtual void visit(MulNode* n) = 0;
    virtual void visit(DivNode* n) = 0;
    virtual void visit(ListNode* n) = 0;
    virtual void visit(ConstInt* n) = 0;
    virtual void visit(ConstBool* n) = 0;
    virtual void visit(ConstString* n) = 0;
    virtual void visit(ConstChar* n) = 0;
    virtual void visit(VarNode* n) = 0;
    virtual void visit(VarDefNode* n) = 0;
    virtual void visit(TypeDefNode* n) = 0;
    virtual void visit(AssignNode* n) = 0;
    virtual void visit(LambdaDef* n) = 0;
    virtual void visit(CallNode* n) = 0;
    virtual void visit(PrintNode* n) = 0;
    virtual void visit(PrintlnNode* n) = 0;
    virtual void visit(IfNode* n) = 0;
    virtual void visit(CmpNode* n) = 0;
};

class Dumper : public Visitor {
public:
    virtual void visit(LogicOrNode* n);
    virtual void visit(LogicNotNode* n);
    virtual void visit(LogicAndNode* n);

    virtual void visit(BitOrNode* n);
    virtual void visit(BitXorNode* n);
    virtual void visit(BitAndNode* n);
    virtual void visit(LeftShiftNode* n);
    virtual void visit(RightShiftNode* n);

    virtual void visit(AddNode* n);
    virtual void visit(SubNode* n);
    virtual void visit(MulNode* n);
    virtual void visit(DivNode* n);
    virtual void visit(ListNode* n);
    virtual void visit(ConstInt* n);
    virtual void visit(ConstBool* n);
    virtual void visit(ConstString* n);
    virtual void visit(ConstChar* n);
    virtual void visit(VarNode* n);
    virtual void visit(VarDefNode* n);
    virtual void visit(TypeDefNode* n);
    virtual void visit(AssignNode* n);
    virtual void visit(LambdaDef* n);
    virtual void visit(CallNode* n);
    virtual void visit(PrintNode* n);
    virtual void visit(PrintlnNode* n);
    virtual void visit(IfNode* n);
    virtual void visit(CmpNode* n);
};

class StackFrame;
class Object;

class Evaluator : public Visitor {
private:
    StackFrame* _frame;
    Object*     _result;

public:
    Evaluator();
    ~Evaluator();

    virtual void visit(LogicOrNode* n);
    virtual void visit(LogicNotNode* n);
    virtual void visit(LogicAndNode* n);
    virtual void visit(BitOrNode* n);
    virtual void visit(BitXorNode* n);
    virtual void visit(BitAndNode* n);
    virtual void visit(LeftShiftNode* n);
    virtual void visit(RightShiftNode* n);

    virtual void visit(AddNode* n);
    virtual void visit(SubNode* n);
    virtual void visit(MulNode* n);
    virtual void visit(DivNode* n);
    virtual void visit(ListNode* n);
    virtual void visit(ConstInt* n);
    virtual void visit(ConstBool* n);
    virtual void visit(ConstString* n);
    virtual void visit(ConstChar* n);
    virtual void visit(VarNode* n);
    virtual void visit(VarDefNode* n);
    virtual void visit(TypeDefNode* n);
    virtual void visit(AssignNode* n);
    virtual void visit(LambdaDef* n);
    virtual void visit(CallNode* n);
    virtual void visit(PrintNode* n);
    virtual void visit(PrintlnNode* n);
    virtual void visit(IfNode* n);
    virtual void visit(CmpNode* n);
};

#endif
